#include "Node.h"

Node::Node(Node *parent, std::vector<std::vector<int>*> *state) {
	this->parent = parent;
	this->state = state;
	if (parent == NULL) {
		level = 0;
	}
	else {
		level = parent->getLevel() + 1;
	}
	children = new std::vector<Node *>();
}

bool Node::createChild(char direction) {
	Node *child = new Node(this, NULL);
	child->setState(state);
	if (child->changeState(direction)) {
		children->push_back(child);
		return true;
	}
	return false;
}

bool Node::changeState(char direction) {
	this->direction = direction;
	bool flagFind = false;
	bool flagReturn = true;
	std::vector<std::vector<int>*>::iterator it;

	for (int i = 0; i < state->size(); i++) {
		for (int j = 0; j < state->at(i)->size(); j++) {
			if (state->at(i)->at(j) == 0) {
				int temp;
				int horizontal = 0;
				int vertical = 0;

				switch (direction) {
					case 'G':
					case 'g':
						if (i > 0) {
							vertical = -1; 
						}
						else {
							flagReturn = false;
						}
						break;
					case 'L':
					case 'l':
						if (j > 0) {
							horizontal = -1;
						}
						else {
							flagReturn = false;
						}
						break;
					case 'P':
					case 'p':
						if (j < state->at(i)->size()-1) {
							horizontal = 1;
						}
						else {
							flagReturn = false;
						}
						break;
					case 'D':
					case 'd':
						if (i < state->size() - 1) {
							vertical = 1;
						}
						else {
							flagReturn = false;
						}
						break;
					default:
						flagReturn = false;
						break;
				}
				temp = state->at(i)->at(j);
				state->at(i)->at(j) = state->at(i + vertical)->at(j + horizontal);
				state->at(i + vertical)->at(j + horizontal) = temp;
				flagFind = true;
				break;
			}
		}

		if (flagFind) {
			break;
		}
	}
	return flagReturn;
}

void Node::showState() {
	std::vector<std::vector<int>*>::iterator it;

	for (it = state->begin(); it != state->end(); ++it)	{
		std::vector<int>::iterator it2;
		for (it2 = (*it)->begin(); it2 != (*it)->end(); ++it2) {
			std::cout << *it2 << " ";
		}
		std::cout << std::endl;
	}
}

void Node::setState(std::vector<std::vector<int>*> *state) {
	this->state = new std::vector<std::vector<int>*>();
	std::vector<std::vector<int>*>::iterator it;

	for (it = state->begin(); it != state->end(); ++it) {
		std::vector<int> *tempV = new std::vector<int>();
		tempV->reserve((*it)->size());
		copy((*it)->begin(), (*it)->end(), back_inserter(*tempV));
		this->state->push_back(tempV);
	}
}

int* Node::getPosition(int value) {
	for (int i = 0; i < state->size(); i++) {
		for (int j = 0; j < state->at(i)->size(); j++) {
			if (state->at(i)->at(j) == value) {
				int* a = new int[2];
				a[0] = i;
				a[1] = j;
				return a;
			}
		}
	}
}

Node* Node::getParent() {
	return this->parent;
}

std::vector<Node*>* Node::getChildren() {
	return this->children;
}

std::vector<std::vector<int>*>* Node::getState() {
	return this->state;
}

char Node::getDirection() {
	return direction;
}

int Node::getLevel() {
	return level;
}

Node::~Node() {
	std::vector<Node*>::iterator it;

	for (it = children->begin(); it != children->end(); ++it) {
		delete(*it);
	}

	if (parent != NULL) {
		delete(parent);
	}

	std::vector<std::vector<int>*>::iterator it2;

	for (it2 = state->begin(); it2 != state->end(); ++it) {
		delete(*it);
	}
	delete(state);
}
